package com.ruoyi.camp.Handler;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.utils.spring.SpringUtils;
//import com.ruoyi.camp.domain.OnlineService;
import com.ruoyi.camp.domain.SocketMsg;
import com.ruoyi.camp.service.RedisService;
//import com.ruoyi.camp.service.impl.OnlineServiceServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

@Component
public class ChatWebSocketHandler extends TextWebSocketHandler {


    private static final Logger log = LoggerFactory.getLogger(ChatWebSocketHandler.class);

    @Resource
    private RedisService redisService = SpringUtils.getBean(RedisService.class);

//    @Autowired
//    private OnlineServiceServiceImpl onlineServiceService;


    //用来存放每个客户端对应的MyWebSocket对象。
    private static CopyOnWriteArraySet<ChatWebSocketHandler> webSocketSet = new CopyOnWriteArraySet<ChatWebSocketHandler>();
    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private WebSocketSession session;

    private String uuid;
    private String customerServiceID;
    private final String serverUUID = "888888888888888888888";

    //用来记录sessionId和该session进行绑定
    private static Map<String, WebSocketSession> map = new HashMap<String, WebSocketSession>();


    @Value("${wechart.wxUserRole}")
    private String wxUserRole;
    // 连接成功后调用
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        Long roleId = (Long)session.getAttributes().get("roleId");
        String userId = (String)session.getAttributes().get("userId");
        String nickName = (String)session.getAttributes().get("nickName");
        String userName = (String)session.getAttributes().get("userName");

        if (roleId != Long.valueOf(wxUserRole)) {
            userId = serverUUID;
        }
        this.session = session;
        this.uuid = userId;

        Map<String, Object> serverInfo = new HashMap<>();
        serverInfo.put("ip", "127.0.0.1");
        serverInfo.put("uuid", serverUUID);
        serverInfo.put("nickname", "客服");
        //把生成的信息存到redis中,以便MyWebSocket.onOpen 的时候查询UUID对应的Nickname
        redisService.set("USER_INFO:" + serverUUID, serverInfo);

        map.put(uuid, session);

        webSocketSet.add(this);     //加入set中
        System.out.println("有新连接加入:" + uuid + ",当前在线人数为" + webSocketSet.size());

        // 如果是客服连接上了
        if (uuid.equals(serverUUID)) {

            //获取近7天所有用户的聊天记录的UUID
            Set<String> allUser = redisService.getKeys("USER_CHAT_RECORDS:*");
            //获取在线用户的UUID
            Set<String> onlyUUID = new HashSet<>(map.keySet());
            System.out.println("目前有:"+onlyUUID.size()+"位,在线的人:"+onlyUUID);
            //遍历redis中的每个元素,截取UUID,放到onlyUUID的set中
            for (String user : allUser) {
                onlyUUID.add(user.substring(18));
            }
            //set转list
            List<String> allUUID = new ArrayList<>(onlyUUID);

            //去除客服UUID
            allUUID.remove(serverUUID);

            //查询近7天所有用户的聊天记录
            List<Map<String, Object>> allUserInfo = new ArrayList<>();

            for (int i = 0; i < allUUID.size(); i++) {
                Map<String, Object> userInfo = new HashMap<>();
                Object o = redisService.get("USER_INFO:" + allUUID.get(i));
                //拼装userInfo
                if (!ObjectUtils.isEmpty(o)) {
                    Map<String, String> mp = (Map<String, String>) o;
                    userInfo.put("uuid", mp.get("uuid"));
                    userInfo.put("ip", mp.get("ip"));
                    userInfo.put("nickname", mp.get("nickname"));
                    userInfo.put("alive", map.containsKey(mp.get("uuid")) ? 1 : 0);
                    //在redis中查找这个user的所有聊天记录
                    Object o1 = redisService.getList("USER_CHAT_RECORDS:" + mp.get("uuid"));
                    List<Map<String, Object>> chatRecords = new ArrayList<>();
                    if (o1 != null) {
                        chatRecords = (List<Map<String, Object>>) o1;
                    }
                    userInfo.put("chatRecords", chatRecords);
                    //装到allUserInfo中
                    allUserInfo.add(userInfo);
                }
            }

            //newMap数据结构在最下方
            Map<String, Object> newMap = new HashMap<String, Object>();
            newMap.put("allUUID", allUserInfo);
            newMap.put("toServer", 1);
            // msgType: 0 首次连线通知  1 普消通知  2 下线通知  3上线通知 4客服不在线通知
            newMap.put("msgType", 0);

            String jsonStr = JSONObject.toJSONString(newMap);

            // 客服上线收到的消息 {"allUUID":[], "toServer":1}
            this.session.sendMessage(new TextMessage(jsonStr));
            //循环发送给所有!!在线!!的用户msgType: 1, fromUser: '888888888888888888888'
            for (int i = 0; i < allUserInfo.size(); i++) {

                if ((int) allUserInfo.get(i).get("alive") == 1) {
                    String tempUUID = String.valueOf(allUserInfo.get(i).get("uuid"));
                    Map<String, Object> userMap = new HashMap<String, Object>();
                    userMap.put("toUser", 1);
                    userMap.put("serverAlive", map.get(serverUUID) != null); // 客服是否在线
                    userMap.put("msgType", 3);
                    String userStr = JSONObject.toJSONString(userMap);
                    //通过系统通知发送
                    if (map.get(tempUUID) != null && map.get(tempUUID).isOpen()) {

                        map.get(tempUUID).sendMessage(new TextMessage(userStr));
                    }
                }
            }


        } else {

            //把生成的信息存到redis中,以便MyWebSocket.onOpen 的时候查询UUID对应的Nickname

            // 如果是用户连接上了
            Map<String, Object> newMap = new HashMap<String, Object>();

            newMap.put("toUser", 1);
            newMap.put("msgType", 0);
            // redis 中查询这个用户近7天的历史聊天记录
            Object o = redisService.getList("USER_CHAT_RECORDS:" + uuid);
            List<Map<String, Object>> chatRecords = new ArrayList<>();
            if (!ObjectUtils.isEmpty(o)) {
                chatRecords = (List<Map<String, Object>>) o;
            }
            Map<String, Object> userInfo = new HashMap<String, Object>();
            userInfo.put("chatRecords", chatRecords);
            userInfo.put("uuid", uuid);
            userInfo.put("nickname", nickName);
            userInfo.put("ip", "127.0.0.1");

            userInfo.put("username", userName);
            //根据uuid查询用户信息
            redisService.set("USER_INFO:"+userId,userInfo);
            Object userO = redisService.get("USER_INFO:" + uuid);
            Map<String, String> mp = (Map<String, String>) userO;
            if (!ObjectUtils.isEmpty(userO)) {
                userInfo.put("userName", mp.get("nickname"));
                userInfo.put("ip", mp.get("ip"));
            } else {
                userInfo.put("userName", "查无此人");
                userInfo.put("ip", "0.0.0.0");
            }
            userInfo.put("serverAlive", map.get(serverUUID) != null);
            newMap.put("userInfo", userInfo);

            //转成json字符串
            String jsonStr = JSONObject.toJSONString(newMap);
            // 用户上线收到的消息  {"serverAlive":true, "toUser":1}
            this.session.sendMessage(new TextMessage(jsonStr));

            //拼一个map转成json字符串 用来给客服发送一个上线的通知
            // msgType: 0 首次连线通知  1 普消通知  2 下线通知  3上线通知 4客服不在线通知
            Map<String, Object> userMap = new HashMap<String, Object>();
            userMap.put("addUUID", this.uuid); //下线用户的UUID
            userMap.put("toServer", 1);
            userMap.put("msgType", 3);
            //从redis中查询新上线的用户nickname
            Object ob = redisService.get("USER_INFO:" + this.uuid);
            if (!ObjectUtils.isEmpty(ob)) {
                Map<String, String> mp2 = (Map<String, String>) ob;
                userMap.put("nickname", mp2.get("nickname"));
                userMap.put("ip", mp2.get("ip"));
            }
            String userStr = JSONObject.toJSONString(userMap);
            //如果客服在线,给客服发送用户消息
            if (map.get(serverUUID) != null && map.get(serverUUID).isOpen()) {
                map.get(serverUUID).sendMessage(new TextMessage(userStr));
//                System.out.println("新用户上线时客服收到的字符串:"+userStr);
            }
        }

    }

    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage textMessage) throws Exception {

        String message = textMessage.getPayload();
        //从客户端传过来的数据是json数据，所以这里使用jackson进行转换为SocketMsg对象，
        //解析字符串
        SocketMsg socketMsg = JSONObject.parseObject(message, SocketMsg.class);
        System.out.println("来自客户端的消息-->" + "发送者:" + socketMsg.getSendType() + ",消息内容:" + socketMsg.getMsg());

        //redis的key全部用用户UUID来标识,时效7天
        if (uuid.equals(serverUUID)) {
            String userUUID = socketMsg.getToUser(); //如果发送者是客服,那保存redis的ID用客户的UUID
            redisService.setList("USER_CHAT_RECORDS:" + userUUID, socketMsg, 60 * 60 * 24 * 7);
        } else {
            redisService.setList("USER_CHAT_RECORDS:" + uuid, socketMsg, 60 * 60 * 24 * 7);
        }


        //单聊消息 socketMsg.getType() == 1
        //单聊.需要找到发送者和接受者.
        System.out.println("message:" + message);
        WebSocketSession fromSession = map.get(socketMsg.getFromUser());
        WebSocketSession toSession = map.get(socketMsg.getToUser());

        System.out.println("message:" + message);
        List<Map<String, Object>> allUserInfo = new ArrayList<>();
        Map<String, Object> userInfo = new HashMap<>();

        //为了保持消息结构一样 打包chatRecords数据
        List<Map<String, Object>> chatRecords = new ArrayList<>();

        Map<String, Object> chatRecord = JSON.parseObject(message);
        chatRecords.add(chatRecord);

        userInfo.put("chatRecords", chatRecords);

        //如果消息是发给客服的
        userInfo.put("uuid", socketMsg.getToUser());
        userInfo.put("ip", socketMsg.getIp());
        userInfo.put("nickname", socketMsg.getToName());
        userInfo.put("alive", map.containsKey(socketMsg.getToUser()) ? 1 : 0);

        //装到allUserInfo中
        allUserInfo.add(userInfo);

        //newMap数据结构在最下方
        Map<String, Object> newMap = new HashMap<String, Object>();
        newMap.put("allUUID", allUserInfo);
        newMap.put("toServer", 1);
        // msgType: 0 首次连线通知  1 普消通知  2 下线通知  3上线通知 4客服不在线通知
        newMap.put("msgType", 1);

        //发送给两位接收者.
        if (toSession != null) {

            String jsonStr = JSONObject.toJSONString(newMap);
            System.out.println("来自客户端的消息-->" + "发送者:" + socketMsg.getSendType() + ",消息内容:" + socketMsg.getMsg());

            //分别发送给两个人

            System.out.println("toSession = " + toSession.getUri());
            System.out.println("fromSession = " + fromSession.getUri());
            fromSession.sendMessage(new TextMessage(jsonStr));
            toSession.sendMessage(new TextMessage(jsonStr));
        } else {
            System.out.println("顾客下线了");

            //如果 顾客下线了
            if (socketMsg.getFromUser().equals(serverUUID)){
                //客服接收到的消息
                chatRecord.put("msg", "对方不在线");
                String jsonStr = JSONObject.toJSONString(newMap);
                fromSession.sendMessage(new TextMessage(jsonStr));

            }else {
                //仅发送给发送者, 因为对方不在线
                // msgType: 0 首次连线通知  1 普消通知  2 下线通知  3上线通知 4客服不在线通知
                newMap.put("msgType", 4);
                chatRecord.put("msg", "客服人工坐席正忙,请稍后...");
                String jsonStr = JSONObject.toJSONString(newMap);

                fromSession.sendMessage(new TextMessage(jsonStr));
            }

        }

    }
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {

        webSocketSet.remove(this);  //从set中删除

        //移除离线人
        map.remove(this.uuid); //
        System.out.println("有一连接关闭！当前在线人数为" + webSocketSet.size());

        //剩下的人
        List<String> newUUID = new ArrayList<>(map.keySet());

        //判断这个uuid是不是客服
        //如果是客服,给所有人发送一条系统消息 serverAlive:false
        if (this.uuid.equals(serverUUID)) {
            //UUID列表中清除客服UUID
            newUUID.remove(serverUUID);
            //循环发送给所有用户msgType: 1, fromUser: '8888888888888888888'
            for (int i = 0; i < newUUID.size(); i++) {
                //通过系统通知发送
                Map<String, Object> userMap = new HashMap<>();
                userMap.put("toUser", 1);
                userMap.put("serverAlive", map.get(serverUUID) != null); // 客服是否在线
                userMap.put("msgType", 2);

                String userStr = JSONObject.toJSONString(userMap);
                if (map.get(newUUID.get(i)) != null && map.get(newUUID.get(i)).isOpen()) {

                    map.get(newUUID.get(i)).sendMessage(new TextMessage(userStr));
                }
            }
        }
        //如果下线的这个uuid 不是客服 ,告诉客服 this.uuid 下线了
        else {
            // msgType: 0 首次连线通知  1 普消通知  2 下线通知  3上线通知 4客服不在线通知
            Map<String, Object> newMap = new HashMap<String, Object>();
            newMap.put("leaveUUID", this.uuid); //下线用户的UUID
            newMap.put("toServer", 1);
            newMap.put("msgType", 2);

            String jsonStr = JSONObject.toJSONString(newMap);

            //用户下线时 客服在线才可以接收消息
            //判断客服在不在线

            if (map.get(serverUUID) != null && map.get(serverUUID).isOpen()) {
                map.get(serverUUID).sendMessage(new TextMessage(jsonStr));
            }

        }
    }

//    private void saveMessageOffline(String senderUserId, String receiverUserId, String content) {
//        OnlineService onlineService = new OnlineService();
//        onlineService.setContent(content);
//        onlineService.setSenderId(senderUserId);
//        onlineService.setReceiverId(receiverUserId);
//        onlineService.setState("0");
//        onlineServiceService.insertOnlineService(onlineService);
//    }

    // 拼接发送的消息
//    private TextMessage buildMessage(String senderUserId, String senderUserName, String payload) {
//        return new TextMessage(senderUserId + ":" + senderUserName + ":" + payload);
//    }
}